#ifndef MESSAGE_SERVER_CLIENT_H
#define MESSAGE_SERVER_CLIENT_H

#include "client-id.h"
#include "message.h"
#include "fingerprint.h"
#include <QtCore>

class FileList;

namespace messages {

// client to server
enum {
    LOGIN = 0,         // done
    S_LIST_SEGMENT,
    S_LIST_FINISH,     // gol
    S_QUERY,           // done
    LOGOUT,            // gol
};

// server to client
enum {
    ACK_LOGIN = 32,    // gol
    NACK_LOGIN,        // gol
    ACK_LIST_SEGMENT,
    ACK_LIST_FINSIH,   // gol
    S_QUERY_RESULT,
    ACK_LIST_HEAD,     // gol
    NACK_LIST_HEAD,    // gol
};

class Login : public Message {
public:
    Login();
    Login(ClientId id, quint32 ip, quint16 port,
          QByteArray name, QByteArray email);

    virtual ~Login() {
    }

    // accesori pentru campurile mesajului

    ClientId id() const {
        return id_;
    }

    quint32 ip() const {
        return ip_;
    }

    quint16 port() const {
        return port_;
    }

    const QByteArray& name() const {
        return name_;
    }

    const QByteArray& email() const {
        return email_;
    }

protected:
    virtual void parse_array(const QByteArray* array, int* position);
    virtual void build_array(QByteArray* array) const;

private:
    ClientId id_;        // identificatorul clientului
    quint32 ip_;         // ip-ul clientului in network byte order
    quint16 port_;       // port-ul clientului in network byte order
    QByteArray name_;    // porecla utilizatorului
    QByteArray email_;   // adresa de email
};

class SQuery : public Message {
public:
    SQuery();
    SQuery(const QByteArray& query, quint32 query_id);

    virtual ~SQuery() {
    }

    const QByteArray& query() const {
        return query_;
    }

protected:
    virtual void parse_array(const QByteArray* array, int* position);
    virtual void build_array(QByteArray* array) const;

private:
    QByteArray query_;   // cautarea
    quint32 query_id_;
};

// mecanismul de trimitere a listelor e in felul urmator
// se trimit cate un ListSegment ce contine cateva fisier
// fiecare este confirmat folosind AckListSegment (un mecanism
// cu fereastra glisanta). cand se termina de trimis toate fisiere
// se trimite un segment cu 0 fisiere care se confirma.

class ListSegment : public Message {
public:
    ListSegment();
    ListSegment(const FileList* list, int start, int end, int id);

    virtual ~ListSegment();

    const FileList* list() const {
        return list_;
    }

    quint32 id() const {
        return id_;
    }

protected:
    virtual void parse_array(const QByteArray* array, int* position);
    virtual void build_array(QByteArray* array) const;

private:
    FileList* list_;          // lista de fisiere
    quint32 id_;              // idul partii curente
};

class AckListSegment : public Message {
public:
    AckListSegment();
    AckListSegment(quint32 id);

    ~AckListSegment() {
    }

protected:
    virtual void parse_array(const QByteArray* array, int* position);
    virtual void build_array(QByteArray* array) const;

private:
    quint32 id_;        // identificatorul segmentului care va fi confirmat
};

class QueryResult : public Message {
public:
    QueryResult();
    QueryResult(quint32 query_id, ClientId client,
                quint32 address, quint16 port, 
    			const QByteArray& filename,
                const FingerPrint& fingerprint,
                quint32 size);

    virtual ~QueryResult() {
    }

protected:
    virtual void parse_array(const QByteArray* array, int* position);
    virtual void build_array(QByteArray* array) const;

private:
	quint32 query_id_;
	ClientId client_;            // numele clientului care detine fisierul
	quint32 address_;            // adresa clientului
	quint16 port_;               // portul pe care asculta noi conexiuni
	QByteArray filename_;        // numele fisierului
	FingerPrint fingerprint_;    // amprenta
	quint32 size_;               // dimensiunea
};


}

#endif
